"""
仓位管理模块
"""
from typing import Optional, Dict, List
from dataclasses import dataclass, field
from datetime import datetime
from src.utils.logger import get_logger

logger = get_logger(__name__)


@dataclass
class Trade:
    """单笔交易记录"""
    trade_id: str
    symbol: str
    entry_time: datetime
    entry_price: float
    entry_qty: float
    side: str  # 'long' or 'short'
    exit_time: Optional[datetime] = None
    exit_price: Optional[float] = None
    exit_qty: Optional[float] = None
    pnl: float = 0.0
    pnl_pct: float = 0.0
    status: str = "open"  # open/closed
    reason: str = ""  # 平仓原因: tp/sl/timeout/manual
    order_ids: List[str] = field(default_factory=list)


class PositionManager:
    """仓位管理器"""

    def __init__(self):
        self.positions: Dict[str, Trade] = {}
        self.closed_trades: List[Trade] = []
        self.trade_counter = 0

    def open_position(self, symbol: str, side: str, price: float,
                     quantity: float, timestamp: datetime) -> Trade:
        """
        开仓

        Args:
            symbol: 交易对
            side: 方向 (long/short)
            price: 入场价格
            quantity: 入场数量
            timestamp: 入场时间

        Returns:
            Trade对象
        """
        self.trade_counter += 1
        trade_id = f"{symbol}_{self.trade_counter}_{int(timestamp.timestamp())}"

        trade = Trade(
            trade_id=trade_id,
            symbol=symbol,
            entry_time=timestamp,
            entry_price=price,
            entry_qty=quantity,
            side=side,
        )

        self.positions[trade_id] = trade
        logger.info(f"开仓: {symbol}, 方向={side}, 价格={price}, 数量={quantity}")

        return trade

    def close_position(self, trade_id: str, exit_price: float,
                      exit_qty: float, timestamp: datetime,
                      reason: str = "", cost_info: Optional[Dict] = None) -> Optional[Trade]:
        """
        平仓

        Args:
            trade_id: 交易ID
            exit_price: 平仓价格
            exit_qty: 平仓数量
            timestamp: 平仓时间
            reason: 平仓原因
            cost_info: 成本信息

        Returns:
            平仓后的Trade对象
        """
        if trade_id not in self.positions:
            logger.warning(f"交易不存在: {trade_id}")
            return None

        trade = self.positions[trade_id]

        # 计算盈亏
        if trade.side == "long":
            pnl = (exit_price - trade.entry_price) * exit_qty
        else:  # short
            pnl = (trade.entry_price - exit_price) * exit_qty

        # 考虑成本
        if cost_info:
            pnl -= cost_info.get('trading_fee', 0)
            pnl -= cost_info.get('funding_fee', 0)

        pnl_pct = (pnl / (trade.entry_price * exit_qty)) * 100 if trade.entry_price > 0 else 0

        # 更新交易信息
        trade.exit_time = timestamp
        trade.exit_price = exit_price
        trade.exit_qty = exit_qty
        trade.pnl = pnl
        trade.pnl_pct = pnl_pct
        trade.status = "closed"
        trade.reason = reason

        # 移出活跃持仓
        del self.positions[trade_id]
        self.closed_trades.append(trade)

        logger.info(f"平仓: {trade.symbol}, 盈亏={pnl:.2f} ({pnl_pct:.2f}%), 原因={reason}")

        return trade

    def get_active_position(self, symbol: str) -> Optional[Trade]:
        """获取特定交易对的活跃持仓"""
        for trade in self.positions.values():
            if trade.symbol == symbol:
                return trade

        return None

    def get_active_positions(self) -> List[Trade]:
        """获取所有活跃持仓"""
        return list(self.positions.values())

    def get_closed_trades(self, symbol: str = None) -> List[Trade]:
        """获取已平仓交易"""
        if symbol:
            return [t for t in self.closed_trades if t.symbol == symbol]
        return self.closed_trades

    def calculate_stats(self) -> Dict:
        """计算交易统计"""
        if not self.closed_trades:
            return {
                'total_trades': 0,
                'winning_trades': 0,
                'losing_trades': 0,
                'win_rate': 0,
                'total_pnl': 0,
                'avg_pnl': 0,
                'avg_win': 0,
                'avg_loss': 0,
                'profit_factor': 0,
            }

        trades = self.closed_trades
        winning = [t for t in trades if t.pnl > 0]
        losing = [t for t in trades if t.pnl < 0]

        total_pnl = sum(t.pnl for t in trades)
        total_wins = sum(t.pnl for t in winning)
        total_losses = sum(t.pnl for t in losing)

        return {
            'total_trades': len(trades),
            'winning_trades': len(winning),
            'losing_trades': len(losing),
            'win_rate': (len(winning) / len(trades) * 100) if trades else 0,
            'total_pnl': total_pnl,
            'avg_pnl': total_pnl / len(trades) if trades else 0,
            'avg_win': total_wins / len(winning) if winning else 0,
            'avg_loss': total_losses / len(losing) if losing else 0,
            'profit_factor': abs(total_wins / total_losses) if total_losses != 0 else 0,
        }
